package gui.logado.chat;

import conexao.Http;
import conexao.HttpData;
import conexao.HttpListener;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.*;
import recados.Recados;

public class Chat extends Form implements CommandListener, HttpListener {

    //Tela Escrita
    private final TextBox campoMensagem;
    private final Command cmdEscrever;
    private final Command cmdVoltar;
    private final Command cmdAtualizar;
    private final Recados midlet;
    private Http updater;
    private boolean escreveu;
    private Timer auto_timer;
    private final Command cmdParar;
    private boolean processando = false;
    private final HttpData dados;
    private ImageLoader img_loader;

    public Chat(Recados midlet) {
        super("Chat");

        this.midlet = midlet;

        campoMensagem = new TextBox("Sua Mensagem:", null, 200, TextField.ANY);

        cmdVoltar = new Command("Voltar", Command.BACK, 0);
        cmdEscrever = new Command("Escrever", Command.OK, 1);

        campoMensagem.addCommand(cmdEscrever);
        campoMensagem.addCommand(cmdVoltar);

        campoMensagem.setCommandListener(this);

        cmdAtualizar = new Command("Atualizar", Command.SCREEN, 2);
        cmdParar = new Command("Parar", Command.STOP, 3);

        addCommand(cmdVoltar);
        addCommand(cmdEscrever);
        addCommand(cmdAtualizar);

        setCommandListener(this);

        auto_timer = new Timer();

        updater = new Http("Atualizando");
        updater.setListener(this);

        dados = new HttpData();
        dados.setPagina("/chat.php");
        dados.put("escrever", "false");

        updater.setHttpData(dados);

        img_loader = new ImageLoader();
    }

    public void commandAction(Command c, Displayable d) {
        if (d == this) {
            if (c == cmdVoltar) {
                exitChat();
                Recados.setCurrent(midlet.getPrincipal());
            } else if (c == cmdAtualizar) {
                updater.doPost(true);

                removeCommand(cmdAtualizar);
                addCommand(cmdParar);
            } else if (c == cmdParar) {
                updater.cancela();

                removeCommand(cmdParar);
                addCommand(cmdAtualizar);
            } else if (c == cmdEscrever) {
                Recados.setCurrent(campoMensagem);
            }
        } else if (d == campoMensagem) {
            if (c == cmdVoltar) {
                Recados.setCurrent(midlet.getPrincipal());
            } else if (c == cmdEscrever) {
                if (campoMensagem.size() > 0) {
                    escreve();
                    Recados.setCurrent(this);
                } else {
                    Recados.setCurrent(new Alert("Erro", "Digite a mensagem", null, AlertType.ERROR), this);
                }
            }
        }
    }

    private class Updater extends TimerTask {

        public void run() {
            updater.doPost(true);

            removeCommand(cmdAtualizar);
            addCommand(cmdParar);
        }
    }

    public void enterChat() {
        auto_timer = new Timer();
        auto_timer.scheduleAtFixedRate(new Updater(), 200, midlet.getConfig().getAtualizaChat() * 60 * 1000);
    }

    public void exitChat() {
        updater.cancela();
        auto_timer.cancel();
    }

    public void requisicaoCancelada() {
        removeCommand(cmdParar);
        addCommand(cmdAtualizar);
        Recados.setCurrent(this);
    }

    public void falhaRequisiçao(String mensagem) {
        if (midlet.getConfig().isErros()) {
            Recados.setCurrent(new Alert("Erro", mensagem, null, AlertType.ERROR));
        }

        removeCommand(cmdParar);
        addCommand(cmdAtualizar);
    }

    private void escreve() {
        Http writer = new Http("Escrevendo");

        HttpData write_data = new HttpData();
        write_data.setPagina("/chat.php");
        write_data.put("de", midlet.getLoginConfig().getNome());
        write_data.put("escrever", "true");
        write_data.put("mensagem", campoMensagem.getString());

        writer.setHttpData(write_data);
        writer.setListener(this);
        writer.doPost(true);

        escreveu = true;

        removeCommand(cmdAtualizar);
        addCommand(cmdParar);
    }

    public void requisicaoConcluida(DataInputStream in) {

        if (escreveu) {
            campoMensagem.setString("");
            escreveu = false;
        }

        String linhaStatus = Http.readLine(in);

        if (!linhaStatus.equals("ok")) {
            Recados.setCurrent(new Alert("Erro", linhaStatus, null, AlertType.ERROR), this);
            return;
        }

        //TUDO OK

        //Limpa tela
        deleteAll();

        try {
            //HTML
            int item_index = 0;

            StringBuffer buffer = new StringBuffer(1);
            final int N_LENGTH = 0;
            final int M_LEGTH = 1;
            final int NOME = 2;
            final int MENSAGEM = 3;
            final int TAG = 4;
            final int PROPERTY = 5;
            final int PROPERTY_VALUE_CHAR = 6;
            final int PROPERTY_VALUE = 7;
            final int TAGTEXT = 8;
            int estado = N_LENGTH;
            int length = 0;
            int readed = 0;
            char abre = ' ';
            String tag = null;
            String property = null;
            String value;

            for (int i = in.read();
                    i != -1; i = in.read()) {
                char c = (char) i;
                switch (estado) {
                    case N_LENGTH:
                        if (c == '\n') {
                            length = Integer.parseInt(buffer.toString());
                            buffer = new StringBuffer(1);
                            readed = 0;
                            estado = NOME;
                            continue;
                        }
                        buffer.append(c);
                        break;
                    case NOME:
                        buffer.append(c);
                        readed++;
                        if (readed == length) {
                            append(new StringItem("[" + buffer.toString() + "]", null));
                            buffer = new StringBuffer(1);
                            estado = M_LEGTH;
                            readed = 0;
                        }
                        break;
                    case M_LEGTH:
                        if (c == '\n') {
                            length = Integer.parseInt(buffer.toString());
                            buffer = new StringBuffer(1);
                            readed = 0;
                            estado = MENSAGEM;
                            continue;
                        }
                        buffer.append(c);
                        break;
                    case MENSAGEM:
                        if (c == '<') {
                            append(buffer.toString());
                            buffer = new StringBuffer(1);
                            estado = TAG;
                        } else {
                            buffer.append(c);
                        }
                        readed++;
                        if (readed == length) {
                            append(buffer.toString() + "\n");
                            buffer = new StringBuffer(1);
                            estado = N_LENGTH;
                            readed = 0;
                        }
                        break;
                    case TAG:
                        if (c == ' ' || c == '>') {
                            estado = PROPERTY;
                            tag = buffer.toString();
                            buffer = new StringBuffer(1);

                            if (c == '>') {
                                //TODO Handle tags sem prop que mudam estado tagtext
                                estado = MENSAGEM;
                            }

                            if (tag.equals("img")) {
                                item_index = append(new ImageItem(null, null, Item.LAYOUT_DEFAULT, null));
                            }

                            //TODO Tag a e /a
                        } else {
                            buffer.append(c);
                        }
                        readed++;
                        if (readed == length) {
                            estado = N_LENGTH;
                            readed = 0;
                        }
                        break;
                    case PROPERTY:
                        if (c == '=' || c == '>') {
                            property = buffer.toString();
                            buffer = new StringBuffer(1);
                            estado = PROPERTY_VALUE_CHAR;
                            if (c == '>') {
                                //TODO Handle que mudam estado tagtext
                                estado = MENSAGEM;
                            }

                        } else {
                            buffer.append(c);
                        }
                        readed++;
                        if (readed == length) {
                            estado = N_LENGTH;
                            readed = 0;
                        }
                        break;
                    case PROPERTY_VALUE_CHAR:
                        if (c == '\'' || c == '\"') {
                            abre = c;
                        } else {
                            abre = ' ';
                        }
                        estado = PROPERTY_VALUE;
                        readed++;
                        if (readed == length) {
                            estado = N_LENGTH;
                            readed = 0;
                        }
                        break;
                    case PROPERTY_VALUE:
                        if (c == abre || c == '>') {
                            value = buffer.toString();
                            buffer = new StringBuffer(1);
                            if (tag.equals("img")) {
                                if (property.equals("src")) {
                                    img_loader.carrega((ImageItem) get(item_index), value);
                                }
                            }
                            estado = PROPERTY;
                            if (c == '>') {
                                //TAGs tagttext
                                estado = MENSAGEM;
                            }
                        } else {
                            buffer.append(c);
                        }
                        readed++;
                        if (readed == length) {
                            estado = N_LENGTH;
                            readed = 0;
                        }
                        break;
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        removeCommand(cmdParar);
        addCommand(cmdAtualizar);
    }

    public synchronized void add(String de, String msg) {
        //Bloquear e adicionar a tela
        while (processando) {
            try {
                wait();
            } catch (InterruptedException ex) {
            }
        }
        processando = true;

        Vector objs = new Vector(1);
        String buffer = msg;

        while (true) {
            int img_start = buffer.indexOf("<img ");
            int img_end = buffer.indexOf('>', img_start);

            if (img_start < 0) {
                //Nao tem mais imagens
                //Adiciona o que sobrou do buffer
                objs.addElement(buffer);
                break;
            }

            //Adiciona o que ta antes da imagem se a prieira coisa (que ta no index 0) nao for imagem
            if (img_start > 0) {
                objs.addElement(buffer.substring(0, img_start));
            }

            //Pega pedaço
            String codigo = buffer.substring(img_start, img_end + 1);

            //Deixa so o que tem depois da imagem no buffer
            buffer = buffer.substring(img_end + 1);

            String url = getProperty(codigo, "src");
            String alt = getProperty(codigo, "alt");

            Image img = null;

            if (url.startsWith("http://")) {
                if (midlet.getConfig().isImagensChat()) {
                    try {
                        HttpConnection conn = (HttpConnection) Connector.open(url);
                        DataInputStream imagem = conn.openDataInputStream();
                        img = Image.createImage(imagem);
                    } catch (IOException ex) {
                        //Qualquer excessao deixa a imagem nula
                        img = null;
                    }
                }
            } else {
                if (url.endsWith(".png") && midlet.getConfig().isSmilesChat()) {
                    url = "/smiles/" + url;
                    try {
                        img = Image.createImage(url);
                    } catch (IOException ex) {
                        //Qualquer excessao deixa a imagem nula
                        img = null;
                    }
                }
            }

            ImageItem imageItem = new ImageItem(null, img, Item.LAYOUT_DEFAULT, alt);
            objs.addElement(imageItem);
        }

        append(new StringItem("[" + de + "]", null));

        for (int i = 0; i < objs.size(); i++) {
            Object item = objs.elementAt(i);

            if (item instanceof String) {
                append((String) item);
            } else if (item instanceof ImageItem) {
                append((ImageItem) item);
            }
        }

        processando = false;

        notifyAll();
    }

    public String getProperty(String codigo, String prop) {
        String open = prop + "=\"";

        int src = codigo.indexOf(open);
        int src_end = codigo.indexOf('"', src + 5);

        if (src < 0 || src_end < 0) {
            return "";
        }

        String url = codigo.substring(src + open.length(), src_end);

        return url;
    }
}
